package com.gopay.bis.pab.bcdl.operation;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gopay.common.cipher.utils.LoggerMaskUtils;
import com.gopay.common.constants.bank.PabConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.pab.bcdl.PABOnlineHeaderMessage;
import com.gopay.common.domain.bank.pab.bcdl.PABOnlineMessage;
import com.gopay.common.domain.bank.pab.bcdl.res.ResPAB4004;
import com.gopay.common.domain.bank.pab.bcdl.res.ResPAB4005;
import com.gopay.common.exception.GopayException;
import com.gopay.common.util.xml.tools.XmlToolsService;

public class PabBcdlTransformer {
	
	private final Logger logger = LoggerFactory.getLogger(PabBcdlTransformer.class);
	private static final String xmlEncoding="";
	@Resource(name = "xmlToolsService")
	private XmlToolsService xmlToolsService;
	
	/**
	 * 格式化请求报文
	 * 
	 * @param request
	 * @return String
	 * @throws GopayException
	 */
	public String format(PABOnlineMessage request)throws GopayException {
		try{
			String header = "";
			String bodyXml = "";
			String fileContext = "";
			String sign = "";
			bodyXml = xmlToolsService.j2xml("pab_req_" + request.getHeader().getTxnType().trim(),request, xmlEncoding);
			bodyXml = bodyXml.replaceAll("\r", "").replaceAll("\n", "");
			// 报文头的长度域
			String msgLength = "0";
			msgLength = getBodyLength(bodyXml);
			request.getHeader().setMsgLength(msgLength);
			header = request.getHeader().getHeaderStr();
			fileContext = "";// 不考虑附件
			// 报文头+报文体+附件+签名（签名由银行完成）
			String msg = header + bodyXml + fileContext + sign;
			return msg;
		}catch(Exception e){
			logger.error("PabBcdlTransformer Exception：",e);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6046);
		}
	}

	/**
	 * 报文体长度
	 * 
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	private String getBodyLength(String bodyXml)throws GopayException {
		try{
			return String.valueOf(bodyXml.getBytes(xmlEncoding).length);
		}catch(Exception e){
			logger.error("PabBcdlTransformer Exception：",e);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6046);
		}
	}

	/**
	 * 
	 * @param resStr
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public PABOnlineMessage parse(Object receivedMsgData) throws GopayException {
		try{
			byte[] resBytes = null;
			if (receivedMsgData instanceof byte[]) {
				resBytes = (byte[]) receivedMsgData;
			} else if (receivedMsgData instanceof String) {
				try {
					resBytes = ((String) receivedMsgData).getBytes("GBK");
				} catch (UnsupportedEncodingException e) {
					logger.error("深发展银行(SDB)处理出错，error：" + e);
				}
			}
			if (resBytes == null) {
				logger.error("深发展银行(SDB)处理出错，resBytes为null");
			}
			//logger.error("pab resbyte-->str: " + new String(resBytes, xmlEncoding));
			/**央行检测 要求身份照掩码处理 sj 2017-11-02*/
			logger.error("pab resbyte-->str: " + LoggerMaskUtils.maskString(new String(resBytes, xmlEncoding)));
			// 报文头
			logger.info("pab resbyte header-->" + getString2Trim(resBytes, 0, PabConstants.ONLINE_HEADER_LEN));
			// 报文长度
			int lengthInt = Integer.parseInt(getString2Trim(resBytes, 30, 10).trim());
			// 附件数目
			int fileCountInt = Integer.parseInt(getString2Trim(resBytes, 221, 1).trim());
			// 报文体
			String body = "";
			// 附件（所有的附件），目前不考虑
			String fileStr = "";
			if (lengthInt > 0) {
				body = getString2Trim(resBytes, PabConstants.ONLINE_HEADER_LEN, lengthInt);
				/**央行检测 要求身份照掩码处理 sj 2017-11-02*/
				logger.info("pab resbyte body-->" + LoggerMaskUtils.maskString(body));
			}
			if (fileCountInt > 0) {
				// 暂不考虑附件情况
			}
			PABOnlineMessage res = dealResVo(Arrays.copyOf(resBytes, PabConstants.ONLINE_HEADER_LEN), body, fileStr);
			return res;
		}catch(Exception e){
			logger.error("PabBcdlTransformer Exception：",e);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6046);
		}

	}

	/**
	 * 解析字符串，组装平台vo对象
	 * 
	 * @param res
	 * @param header
	 * @param body
	 * @param fileStr
	 * @throws UnsupportedEncodingException 
	 */
	private PABOnlineMessage dealResVo(byte[] headerByte, String body,String fileStr) throws GopayException {
		try{
			PABOnlineMessage msg = null;
			PABOnlineHeaderMessage header = new PABOnlineHeaderMessage();
			/* 报文头赋值 */
			header.setMsgType(getString2Trim(headerByte, 0, 6));
			header.setMsgCharset(getString2Trim(headerByte, 6, 2));
			header.setProtocol(getString2Trim(headerByte, 8, 2));
			header.setMerchantCode(getString2Trim(headerByte, 10, 20));
			header.setMsgLength(getString2Trim(headerByte, 30, 10));
			header.setTxnType(getString2Trim(headerByte, 40, 6));
			header.setUserOpid(getString2Trim(headerByte, 46, 5));
			header.setServiceFlag(getString2Trim(headerByte, 51, 2));
			header.setOrderDate(getString2Trim(headerByte, 53, 8));
			header.setOrderTime(getString2Trim(headerByte, 61, 6));
			header.setOrderId(getString2Trim(headerByte, 67, 20));
			header.setRetCd(getString2Trim(headerByte, 87, 6));
			header.setRemark(getString2Trim(headerByte, 93, 100));
			header.setRepeatFlag(getString2Trim(headerByte, 193, 1));
			header.setReqCount(getString2Trim(headerByte, 194, 3));
			header.setSignFlag(getString2Trim(headerByte, 197, 1));
			header.setSignFormat(getString2Trim(headerByte, 198, 1));
			header.setSignAlgorithm(getString2Trim(headerByte, 199, 12));
			header.setSignLength(getString2Trim(headerByte, 211, 10));
			header.setFileCount(getString2Trim(headerByte, 221, 1));
			/* 报文头赋值 */
			/* 报文体 */
			if (StringUtils.isNotEmpty(body)) {
				msg = (PABOnlineMessage) xmlToolsService.xml2j("pab_res_"+ header.getTxnType().trim(), body);
			} else {
				if (PabConstants.ONLINE_TXN_TYPE_4004.equals(header.getTxnType().trim())) {
					msg = new ResPAB4004();
				} else if (PabConstants.ONLINE_TXN_TYPE_4005.equals(header.getTxnType().trim())) {
					msg = new ResPAB4005();
				}
			}
			/* 报文体 */
			/* 附件 */
			if (StringUtils.isNotEmpty(fileStr)) {
				// 处理附件
			}
			/* 附件 */
			msg.setHeader(header);
			return msg;
		}catch(Exception e){
			logger.error("PabBcdlTransformer Exception：",e);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6046);
		}
	}

	/**
	 * 
	 * @param str
	 * @param index
	 * @param len
	 * @return
	 * @throws UnsupportedEncodingException 
	 */
	private String getString2Trim(byte[] str, int index, int len) throws GopayException {
		try {
			return new String(str, index, len, xmlEncoding);
		} catch (UnsupportedEncodingException e) {
			logger.error("PabBcdlTransformer Exception：",e);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6046);
		}
	}
}
